package xyz.scootaloo.oj.leetcode

import org.junit.Test
import xyz.scootaloo.common.TestDsl

/**
 * 未解决
 *
 * 1. 如果地雷被挖出, 则将这个位置上的地雷('M')标记为'X'
 * 2. 如果一个相邻没有与地雷相邻的空方块('E')被挖出, 修改它为'B', 并将其所有相邻的方块都应该递归的被挖出
 * 3. 如果一个至少与一个地雷相邻的空方块（'E'）被挖出，修改它为数字（'1'到'8'），表示相邻地雷的数量。
 * 4. 如果在此次点击中，若无更多方块可被揭露，则返回面板。
 *
 * @author flutterdash@qq.com
 * @since 2021/7/1 21:06
 */
class P529 : TestDsl {

    private fun updateBoard(board: Array<CharArray>, click: IntArray): Array<CharArray> {
        val row = board.size
        val column = board[0].size
        val path = Array(row) { BooleanArray(column) }
        val direction = arrayOf(
            intArrayOf(-1, 0),
            intArrayOf(1, 0),
            intArrayOf(0, 1),
            intArrayOf(0, -1),
            intArrayOf(-1, -1),
            intArrayOf(1, 1),
            intArrayOf(-1, 1),
            intArrayOf(1, -1)
        )

        fun replace(r: Int, c: Int, flag: Char) {
            board[r][c] = flag
        }

        fun checkBorder(r: Int, c: Int): Boolean {
            return (r >= 0) && (r < row) && (c >= 0) && (c < column)
        }

        fun traverse(r: Int, c: Int, handle: (nextR: Int, nextC: Int, isValid: Boolean) -> Unit) {
            for (direct in direction) {
                val nextR = r + direct[0]
                val nextC = c + direct[1]
                val isValid = checkBorder(nextR, nextC)
                handle(nextR, nextC, isValid)
            }
        }

        fun searchBoom(r: Int, c: Int): Int {
            var boomCount = 0
            traverse(r, c) {
                nextR, nextC, isValid ->
                if (isValid && board[nextR][nextC] == 'M') {
                    boomCount++
                }
            }
            return boomCount
        }

        fun mark(r: Int, c: Int) {
            var boomCount = searchBoom(r, c)
            board[r][c] = if (boomCount == 0) 'B' else '0' + boomCount
            path[r][c] = true
            traverse(r, c) {
                nextR, nextC, isValid ->
                if (isValid && board[nextR][nextC] == 'E') {
                    boomCount = searchBoom(nextR, nextC)
                    board[nextR][nextC] = if (boomCount == 0) 'B' else '0' + boomCount
                }
            }
        }

        fun search(r: Int, c: Int) {
            if (board[r][c] == 'M')
                return replace(r, c, 'X')
            mark(r, c)
            traverse(r, c) {
                nextR, nextC, isValid ->
                if (isValid && board[nextR][nextC] == 'B') {
                    if (!path[nextR][nextC])
                        search(nextR, nextC)
                }
            }
        }

        val r = click[0]
        val c = click[1]
        search(r, c)
        return board
    }

    @Test
    fun test0() {
        val input = arrayOf(
            charArrayOf('E', 'E', 'E', 'E', 'E'),
            charArrayOf('E', 'E', 'M', 'E', 'E'),
            charArrayOf('E', 'E', 'E', 'E', 'E'),
            charArrayOf('E', 'E', 'E', 'E', 'E'),
        )

        updateBoard(input, intArrayOf(3, 0))

        printIntArray(input)
    }

    private fun printIntArray(arrays: Array<CharArray>) {
        for (array in arrays) {
            println(array)
        }
    }

}
